#!/usr/bin/python
# -*- coding: utf-8 -*-

#在做表项目的添加时，只调用 GetAutoIncrementCount(CounterName) 就可以了
#仅仅想获取当前的个数，可调用 GetCount(CounterName)

from google.appengine.api import memcache 
from google.appengine.ext import db 
import random 
 
class CGeneralCounterShardConfig(db.Model): 
    """Tracks the number of shards for each named counter.""" 
    CounterName = db.StringProperty(required=True) 
    NumberShards = db.IntegerProperty(required=True, default=20) 
 
 
class CGeneralCounterShard(db.Model): 
    """Shards for each named counter""" 
    CounterName = db.StringProperty(required=True) 
    Count = db.IntegerProperty(required=True, default=0) 
  
            
def GetCount(OneCounterName): 
    """Retrieve the value for a given sharded counter. 
    
    Parameters: 
        name - The name of the counter  
    """ 
    Total = memcache.get(OneCounterName) 
    if Total is None: 
        Total = 0 
        for Counter in CGeneralCounterShard.all().filter('CounterName = ', OneCounterName): 
            Total += Counter.Count 
        memcache.add(OneCounterName, Total, 60) 
    return Total 
 
  
def Increment(OneCounterName): 
    """Increment the value for a given sharded counter. 
    
    Parameters: 
        name - The name of the counter  
    """ 
    Config = CGeneralCounterShardConfig.get_or_insert(OneCounterName, CounterName = OneCounterName) 
    def txn(): 
        Index = random.randint(0, Config.NumberShards - 1) 
        ShardName = OneCounterName + str(Index)
        Counter = CGeneralCounterShard.get_by_key_name(ShardName) 
        if Counter is None: 
            Counter = CGeneralCounterShard(key_name=ShardName, CounterName=OneCounterName) 
        Counter.Count += 1 
        Counter.put() 
    db.run_in_transaction(txn) 
    memcache.incr(OneCounterName)
 
#重新设置一个计数器的分片个数，一般用不着
def IncreaseShards(OneCounterName, NewNumberShards):
    """Increase the number of shards for a given sharded counter. 
    Will never decrease the number of shards. 
    
    Parameters: 
        name - The name of the counter 
        num - How many shards to use 
    
    """ 
    Config = CGeneralCounterShardConfig.get_or_insert(OneCounterName, name=OneCounterName) 
    def txn(): 
        if Config.NumberShards < NewNumberShards: 
            Config.NumberShards = NewNumberShards 
            Config.put()    
    db.run_in_transaction(txn)

#获得自动加1后的计数
def GetAutoIncrementCount(OneCounterName):
    Increment(OneCounterName)
    return GetCount(OneCounterName)
